
#ifndef thd421_h__
#define thd421_h__

#pragma once

#include <future>
#include <iostream>
#include <string>

namespace thd421
{

int find_the_answer_to_ltuae()
{
	std::cout << "find_the_answer_to_ltuae\n" << std::endl;
	return 42;
}

void do_other_stuff()
{
	std::cout << "do_other_stuff\n" << std::endl;
}

struct X
{
	void foo(int i, std::string const& str) 
	{
		std::cout << "X::foo " << i << " " << str.c_str() << std::endl;
	}
	std::string bar(std::string const& str) 
	{
		std::cout << "X:bar " << str.c_str() << std::endl;
		return str;
	}
};

struct Y
{
	double operator()(double v)
	{
		std::cout << v << std::endl;
		return v;
	}
};

class move_only
{
public:
	move_only()
	{

	}
	move_only(move_only&& obj): val(std::move(obj.val))
	{

	}
	move_only(move_only const&) = delete;
	move_only& operator=(move_only&& obj)
	{
		this->val = obj.val;
		return *this;
	}
	move_only& operator=(move_only const&) = delete;
	void operator()()
	{

	}

private:
	int val{9};
};



int thd421_test()
{
// 	std::future<int> the_answer = std::async(find_the_answer_to_ltuae);
// 	do_other_stuff();
// 	std::cout << "The answer is " << the_answer.get() << std::endl;

	X x;
	auto f1 = std::async(&X::foo, &x, 42, "hello");
	auto f2 = std::async(&X::bar, x, "goodbye");
	auto f3 = std::async(&X::foo, x, 43, "hello43");



	Y y;
	auto f4 = std::async(Y(), 3.141);
	auto f5 = std::async(std::ref(y), 2.718);
// 	X baz(X&);
// 	auto f6 = std::async(baz, std::ref(x));
	auto f6 = std::async(move_only());

	f1.get();
	f2.get();
	f3.get();
	f4.get();
	f5.get();
	f6.get();

	return 1;
}

}
#endif // thd421_h__